package cn.edu.xmist.singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class SingletonTest {
    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        /**
         * 懒汉式单例模式(有线程安全问题)
         */
        Singleton1 singleton1 = Singleton1.getSingleton1();
        Singleton1 singleton2 = Singleton1.getSingleton1();

        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton2.hashCode() = " + singleton2.hashCode());

        // 通过反射，序列化破坏单例模式
        // 通过类加载获取属性
        Constructor<Singleton1>[] constructors = (Constructor<Singleton1>[]) Singleton1.class.getDeclaredConstructors();
        if (constructors != null && constructors.length>0) {
            Constructor constructor = constructors[0];
            // 因为构造方法是私有的，需要设置权限
            constructor.setAccessible(true);
            Singleton1 singleton1_1 = (Singleton1)constructor.newInstance();
            System.out.println("singleton1_1.hashCode() = " + singleton1_1.hashCode());
        }

        /**
         * 饿汉式单例模式
         */
        Singleton2 singleton3 = Singleton2.getSingleton2();
        Singleton2 singleton4 = Singleton2.getSingleton2();

        /**
         * hashCode 可以简单理解为对象的内存地址，如果code一样，代表同一个对象
         */
        System.out.println("singleton3.hashCode() = " + singleton3.hashCode());
        System.out.println("singleton4.hashCode() = " + singleton4.hashCode());

        /**
         * 懒汉式单例模式(无线程安全问题，采用加锁synchronized)
         */
        CurrentSingleton1 singleton5 = CurrentSingleton1.getSingleton1();
        CurrentSingleton1 singleton6 = CurrentSingleton1.getSingleton1();

        System.out.println("singleton5.hashCode() = " + singleton5.hashCode());
        System.out.println("singleton6.hashCode() = " + singleton6.hashCode());


        /**
         * 枚举单例模式
         */
        EunmSingleton eunmSingleton = EunmSingleton.getInstance();
        System.out.println("eunmSingleton.hashCode() = " + eunmSingleton.hashCode());

        // 通过反射，序列化破坏单例模式
        // 通过类加载获取属性
        Constructor<EunmSingleton>[] constructors2 = (Constructor<EunmSingleton>[]) EunmSingleton.class.getDeclaredConstructors();
        if (constructors2 != null && constructors2.length>0) {
            Constructor constructor = constructors2[0];
            // 因为构造方法是私有的，需要设置权限
            constructor.setAccessible(true);
            EunmSingleton eunmSingleton2 = (EunmSingleton)constructor.newInstance();
            System.out.println("eunmSingleton2.hashCode() = " + eunmSingleton2.hashCode());
        }




    }
}
